package mat;



import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Random;

import jcifs.smb.SmbFile;
import jcifs.smb.SmbRandomAccessFile;

import org.apache.log4j.Logger;

public class MultiProtocolFile_SMB implements IMultiProtocolFile
{
	protected static final int NUM_RETRIES = 10;
	
	protected String path;
	protected SmbFile smbFile;
	
	public MultiProtocolFile_SMB(String path) throws IOException
	{
		this.path = path;
		this.smbFile = new SmbFile(path, MultiProtocolAuthenticationHandler.getInstance().getAuthForSmb(path));
	}
	
	public MultiProtocolFile_SMB(SmbFile smbFile) throws IOException
	{
		this.smbFile = smbFile;
		this.path = smbFile.toString();
	}
	
	//
	// IMultiProtocolFile
	//
	
	@Override
	public InputStream getInputStream() throws IOException
	{
		return smbFile.getInputStream();
	}

	@Override
	public ISeekableDataIO getRandomAccessFile(String mode) throws IOException
	{
		return null;// new SeekableDataIO_SMB(new SmbRandomAccessFile(smbFile, mode));
	}
	
	@Override
	public OutputStream getOutputStream() throws IOException
	{
		return getOutputStream(false);
	}
	
	@Override
	public OutputStream getOutputStream(boolean append) throws IOException
	{
		if (!append && smbFile.exists())
		{
			smbFile.delete();
		}
		
		return smbFile.getOutputStream();
	}
	
	@Override
	public boolean exists()
	{
		for (int i=0; i<NUM_RETRIES; i++)
		{
			try
			{
				return smbFile.exists();
			}
			catch (IOException e)
			{
				if (i+1 >= NUM_RETRIES)
				{
					e.printStackTrace();
					return false;
				}
				else
				{
					safeSleep("exists", e);
				}
			}
		}
		
		return false;
	}
	
	@Override
	public boolean canRead() throws IOException
	{
		return smbFile.canRead();
	}
	
	@Override
	public boolean canWrite() throws IOException
	{
		return smbFile.canWrite();
	}
	
	@Override
	public long lastModified() throws IOException
	{
		return smbFile.lastModified();
	}
	
	@Override
	public long length() throws IOException
	{
		return smbFile.length();
	}
	
	@Override
	public MultiProtocolFile[] listFiles() throws IOException
	{
		SmbFile[] lf = smbFile.listFiles();
		
		if (lf == null || lf.length < 1)
			return new MultiProtocolFile[0];
		
		MultiProtocolFile[] res = new MultiProtocolFile[lf.length];
		for (int i=0; i<lf.length; i++)
			res[i] = new MultiProtocolFile(lf[i]);
		
		return res;
	}
	
	@Override
	public boolean mkdirs()
	{
		try
		{
			if (smbFile.exists())
				return false;
			
			smbFile.mkdirs();
			return true;
		}
		catch (IOException e)
		{
			e.printStackTrace();
			return false;
		}
	}
	
	@Override
	public boolean createNewFile() throws IOException
	{
		smbFile.createNewFile();
		return smbFile.exists();
	}
	
	@Override
	public boolean delete()
	{
		try
		{
			if (!smbFile.exists())
				return false;
			
			smbFile.delete();
			return true;
		}
		catch (IOException e)
		{
			e.printStackTrace();
			return false;
		}
	}
	
	@Override
	public boolean setLastModified(long time)
	{
		try
		{
			smbFile.setLastModified(time);
			return true;
		}
		catch (Exception e)
		{
			e.printStackTrace();
			return false;
		}
	}
	
	@Override
	public long getLastModified()
	{
		return smbFile.getLastModified();
	}
	
	@Override
	public boolean renameTo(IMultiProtocolFile dest) throws IOException
	{
		if (dest instanceof MultiProtocolFile)
			dest = ((MultiProtocolFile)dest).impl;
		
		if (dest instanceof MultiProtocolFile_SMB)
		{
			try
			{
				this.smbFile.renameTo(((MultiProtocolFile_SMB)dest).smbFile);
				return true;
			}
			catch (Exception e)
			{
				e.printStackTrace();
				return false;
			}
		}
		
		throw new IOException("Unsupported Cross FS renameTo: " + this.toString() + " -> " + dest.toString());
	}

	@Override
	public String toString()
	{
		return path;
	}
	
	
	@Override
	public String getPath()
	{
		return smbFile.getCanonicalPath();
	}
	
	@Override
	public String getParent()
	{
		return smbFile.getParent();
	}
	
	@Override
	public String getName()
	{
		return smbFile.getName();
	}
	
	@Override
	public boolean isFile() throws IOException
	{
		return smbFile.isFile();
	}
	
	@Override
	public boolean isDirectory() throws IOException
	{
		return smbFile.isDirectory();
	}
	
	protected void safeSleep(String method, Exception e)
	{
		try
		{
			final long tenSeconds = 5000;
			long delay = (long)(tenSeconds * (1.0 + (new Random()).nextDouble())); 
			Logger.getLogger(this.getClass()).info(method + " failed, Sleeping " + (delay/1000) + " seconds ...", e);
			Thread.sleep(delay);
		}
		catch (Exception ee)
		{
			
		}
	}
	
}
